//#include "stdafx.h"
#include "ICA.h"
#include <fcntl.h>
#include <cfloat>
#include <algorithm>
#include <iomanip>

ICA::ICA(void){}
ICA::ICA(int dimension, int CountryNum, int ImpNum, int DecadeNum, double kNumberOfImpact, double RevolutionRate, bool IsEqualParamValAllowed, 
double InAcceptableCostVal, char* LogFileName, char* DataFileName){
	char* m_PlotFileName;

	m_dimension = dimension;
	m_CountryNum = CountryNum;
	m_ImpNum = ImpNum;
	m_DecadeNum = DecadeNum;
	m_kNumberOfImpact = kNumberOfImpact;
	m_IsEqualParamValAllowed = IsEqualParamValAllowed;// 是否可以势力值重复，默认为是（否尚未实现
	m_RevolutionRate = RevolutionRate;
	m_InAcceptableCostVal = InAcceptableCostVal;
	m_PlotFileName = "Plottest.txt";
	m_Timer.Start();
	if(m_ImpNum >= m_CountryNum){
		cout<<"Error: Impires must be less than countries\n";
		exit(0);
	}

	// 读文件
	m_DataFile.open(DataFileName);
	if(!m_DataFile){
		cout<<"can not open file:" <<DataFileName<<endl;
		exit(0);
	}
	double temp;
	while(!m_DataFile.eof()){
		m_DataFile >> temp;
		m_ParamVal.push_back(temp);
	}
	m_ParamVal_max = *max_element( m_ParamVal.begin(), m_ParamVal.end() );

	// 序号0-总数排列
	for(long long unsigned int i=0; i<m_dimension; i++)
		m_ParamIndex.push_back(i);

	m_LogFile.open(LogFileName);
	if(!m_LogFile){
		cout<<"can not open file:" <<LogFileName<<endl;
		exit(0);
	}
	m_PlotFile.open(m_PlotFileName);
	if(!m_PlotFile){
		cout<<"can not open file:" <<m_PlotFileName<<endl;
		exit(0);
	}
	m_LogFile.clear();
	// 响应时间
	unsigned long int t = m_Timer.GetElapsedTime();
	m_LogFile<<"Second\t"<<t/1000<<":\tICA START\n\tImper="<<m_ImpNum<<"\t Country="<<m_CountryNum
	<<"\tDecades="<<m_DecadeNum<<"\n";
}

/*
ICA::ICA(list<int> ParamIndex, list<int> ParamVal, int CountryNum, int ImpNum, int DecadeNum,
double RevolutionRate, bool IsEqualParamValAllowed, const CostfunType &CostFunc,
double InAcceptableCostVal, string LogFileName): Cost(CostFunc){
	m_ParamIndex = ParamIndex;
	m_ParamVal = ParamVal;
	m_ParamVal_max = *max_element( m_ParamVal.begin(),m_ParamVal.end() );
	m_CountryNum = CountryNum;
	m_ImpNum = ImpNum;
	m_DecadeNum = DecadeNum;
	m_IsEqualParamValAllowed = IsEqualParamValAllowed;
	m_RevolutionRate = RevolutionRate;
	m_InAcceptableCostVal = InAcceptableCostVal;
	m_Timer.Start();

	if(m_ImpNum >= m_CountryNum){
		cout<<"Error: Impires must be less than countries\n";
		exit(0);
	}

	m_LogFile.open(LogfileName);
	if(!m_LogFile){
		cout<<"can not open file:" <<LogfileName<<endl;
		exit(0);
	}


	m_LogFile.clear();
	// 响应时间
	unsigned long int  = m_Timer.GetElapsedTime();
	m_LogFile<<t/1000<<":\tICA START\n Imper="<<m_ImpNum<<"\t Country="<<m_CountryNum
	<<"\tDecades="<<m_DecadeNum<<"\n";
}
*/

// m_CountryList有了所有的国家
void ICA::InitializeCountries(){
	if(!m_CountryList.empty()) return;

	for(int i=0;i<m_CountryNum;i++){
		Country_Profile Profile;
		// 对每一个国家，第key维的量随机在参数表中赋值value
		for (list<int>::iterator it = m_ParamIndex.begin(); it != m_ParamIndex.end(); it++){
			list<double>::iterator itsrc = m_ParamVal.begin();
			advance(itsrc,myrandom( m_ParamVal.size() ));//myrandom
			Profile.Country[(*it)]=(*itsrc);// 传递的是指针，可能有隐患？
		}
		// 根据国家势力值计算cost
		Profile.Cost = Cost(Profile);
		// 不符合就重新抽取
		if(Profile.Cost >= m_InAcceptableCostVal){
			i--;
			continue;
		}
		m_CountryList.push_back(Profile);
	}

	unsigned long int t = m_Timer.GetElapsedTime();
	m_LogFile<<"Second\t"<<t/1000<<":\tCountries have been Initialized.\n";
}

/*
void ICA::InitializeCountries(map<int,int> *Countries, int n){
	// 拷贝m_CountryList = *Countries
	for(int i=0; i<n; i++){
		Country_Profile Profile;
		Profile.Country = Countries[i];
		Profile.Cost = Cost(Profile.Country);
		if(Profile.Cost >= m_InAcceptableCostVal){
			continue;
		}
		m_CountryList.push_back(Profile);
	}

	for(int i=m_CountryList.size(); i<m_CountryNum; i++){
		Country_Profile Profile;
		for (list<int>::iterator it = m_ParamIndex.begin(); it != m_ParamIndex.end(); it++){
			list<int>::iterator itsrc = m_ParamVal.begin();
			advance(itsrc,myrandom(m_ParamVal.size()));
			Profile.Country[(*it)]=(*itsrc);
		}
		Profile.Cost=Cost(Profile.Country);
		if(Profile.Cost>=m_InAcceptableCostVal){
			i--;
			continue;
		}
		m_CountryList.push_back(Profile);
	}

	unsigned long int t=m_Timer.GetElapsedTime();
	m_LogFile<<t/1000<<":\tCountries have been Initialized.\n";
	
}


void ICA::InitializeCountries(list<map<int,int>> Countries){
	for(int i=0; i<Countries.size(); i++){
		// list<map<int,int>>::iterator it=Countries->begin();it!=Countries->end();it++){
		Country_Profile Profile;
		Profile.Country = *(Countries.begin());
		Countries.pop_front();
		Profile.Cost = Cost(Profile.Country);
		if(Profile.Cost >= m_InAcceptableCostVal){
			continue;
		}
		m_CountryList.push_back(Profile);
	}
	for(int i=m_CountryList.size();i<m_CountryNum;i++){
		Country_Profile Profile;
		for (list<int>::iterator it = m_ParamIndex.begin(); it != m_ParamIndex.end(); it++){
			list<int>::iterator itsrc = m_ParamVal.begin();
			advance(itsrc,myrandom(m_ParamVal.size()));
			Profile.Country[(*it)]=(*itsrc);
		}
		Profile.Cost=Cost(Profile.Country);
		if(Profile.Cost >= m_InAcceptableCostVal){
			i--;
			continue;
		}
		m_CountryList.push_back(Profile);
	}
	unsigned long int t=m_Timer.GetElapsedTime();
	m_LogFile<<t/1000<<":\tCountries have been Initialized.\n";
	
}
*/

// 国家按势力排序，前几个国家变成帝国，循环给每个帝国一个殖民地
void ICA::InitializeImpires(){
	// select Imperialists
	m_CountryList.sort();
	Imper_Profile imp;
	// 前几个国家变成帝国
	for(int i=0; i<m_ImpNum; i++){
		imp.Imper = m_CountryList.front();
		m_ImperList.push_back(imp);
		m_CountryList.pop_front();
	}
	// assign colonies
	list<Imper_Profile>::iterator itImp = m_ImperList.begin();
	for(list<Country_Profile>::iterator it = m_CountryList.begin();	it != m_CountryList.end(); it++){
		if(itImp==m_ImperList.end())// 循环给每个帝国一个殖民地
			itImp = m_ImperList.begin();
		itImp->ColonyList.push_back(*it);
		itImp++;
	}

	unsigned long int t = m_Timer.GetElapsedTime();
	m_LogFile<<"Second\t"<<t/1000<<":\tImpers have been constructed.\n";
}

// Cost公式
double ICA::Cost(Country_Profile Kingdom){
	// 代价计算
	for (map<int, double>::iterator iter = Kingdom.Country.begin(); iter != Kingdom.Country.end(); iter++){
		Kingdom.Cost += 1/iter->second;
	}
	return Kingdom.Cost;
}

// 计算所有国家的cost
void ICA::CountryCostCalc(){
	// double MaxCost = 0;
	double temp;
	for(list<Imper_Profile>::iterator itImp = m_ImperList.begin();
	itImp!=m_ImperList.end(); itImp++){
		itImp->TotalCost = 0;// Reset!!!!
		if(!itImp->ColonyList.empty()){// Colony exists
			for(list<Country_Profile>::iterator itCol = itImp->ColonyList.begin();
			itCol!=itImp->ColonyList.end(); itCol++){// 遍历其殖民地
				temp = Cost(*itCol);
				itImp->TotalCost += temp;
				// MaxCost = MaxCost<temp?temp:MaxCost;// 记录最大值
			}
			itImp->TotalCost /= itImp->ColonyList.size();
			itImp->TotalCost *= m_kNumberOfImpact;
			temp = Cost(itImp->Imper)*(1-m_kNumberOfImpact);//reasonable
			itImp->TotalCost += temp;
		}
		else{
			temp = Cost(itImp->Imper);//reasonable
			itImp->TotalCost += temp;
		}
		
		// MaxCost = MaxCost<temp?temp:MaxCost;// 记录最大值
	}
	// 	// 标准化代价
	// for(list<Imper_Profile>::iterator itImp = m_ImperList.begin();
	// itImp!=m_ImperList.end(); itImp++){

	// }
}

// 殖民地某些维度向帝国靠近
void ICA::Assimilate_Clony_to_Imper(){
	double delta;
	bool flag;
	for(list<Imper_Profile>::iterator itImp = m_ImperList.begin(); itImp!=m_ImperList.end();
	itImp++){
		if(!itImp->ColonyList.empty()){// Colony exists
			for(list<Country_Profile>::iterator itCol = itImp->ColonyList.begin();
			itCol!=itImp->ColonyList.end(); itCol++){// 遍历其殖民地
				long long unsigned int n = 0;
				int m = 1;
				while( n++ != itImp->Imper.Country.size() ){//吸收n次
					map<int,double>::iterator it;
					it = itImp->Imper.Country.begin();
					advance( it, myrandom( itImp->Imper.Country.size() ) );// 随机指向该帝国的一个维度
					// [x]为按下标访问，x为key值而非序号
					delta = it->second - itCol->Country[it->first];
					if(delta>1.0 || delta<-1.0){// 该维度value近似不相等（相等则再抽一次）
						flag = delta>0?true:false;
						if(!flag)
							itCol->Country[it->first] -= myrandomd(delta);// 求余看被除数的符号，不看除数
						else
							itCol->Country[it->first] += myrandomd(delta);// 求余看被除数的符号，不看除数
						if(!m--) break;//只吸收一次
					}
				}
				// itCol->Cost=Cost(itCol->Country);
			}
		}
	}
}

// 革命，某殖民地value随机变换
void ICA::Doing_Revolution(){
	int n = int( m_RevolutionRate*m_ImperList.size() );

	for(int i=0; i<n; i++){
		list<Imper_Profile>::iterator itImp = m_ImperList.begin();
		advance( itImp, myrandom(m_ImperList.size()) );

		if(itImp->ColonyList.empty()){// Colony does not exist
			i--;
			continue;
		}
		else{
			list<Country_Profile>::iterator colit = itImp->ColonyList.begin();
			advance( colit, myrandom( itImp->ColonyList.size() ) );//随机一个帝国的一个殖民地
			for(map<int,double>::iterator it1 = colit->Country.begin();
			it1 != colit->Country.end(); it1++){
				list<double>::iterator itsrc = m_ParamVal.begin();
				advance(itsrc,myrandom( m_ParamVal.size() ));
				it1->second = (*itsrc);
				// it1->second = myrandomd(m_ParamVal_max-1)+1;//某维度变化到随机值，在初始参数表中，后续改进
			}
			// colIt->Cost=Cost(colIt->Country);
		}
		
	}
}

// 若殖民地的cost<帝国的cost，则交换殖民地势力与帝国势力
void ICA::Colony_Imper_swap(){
	for(list<Imper_Profile>::iterator itImp=m_ImperList.begin();itImp!=m_ImperList.end();
	itImp++){
		for(list<Country_Profile>::iterator colIt=itImp->ColonyList.begin(); colIt!=itImp->ColonyList.end(); colIt++){
			// colIt->Cost=Cost(colIt->Country);
			if(colIt->Cost < itImp->Imper.Cost){
				colIt->Country.swap(itImp->Imper.Country);
				double temp=colIt->Cost;
				colIt->Cost=itImp->Imper.Cost;
				itImp->Imper.Cost=temp;
			}
		}
	}
}

// 帝国势力排序，将最弱帝国的第一个殖民地（若没有殖民地，则将他自己）给最强帝国
void ICA::Eliminate_Weakest_Imper(){
	double all = 0;
	list<Imper_Profile>::iterator itRandomImp;
	//  = m_ImperList.begin();//gives to the best directly
	for(list<Imper_Profile>::iterator itImp=m_ImperList.begin();itImp!=m_ImperList.end();
	itImp++){
		itImp->ColonyList.sort();
		all += 1/itImp->TotalCost;
	}
	double xrandom = myrandomd(all);
	// 抽一个帝国吸收，帝国越强越容易被抽到
	for(list<Imper_Profile>::iterator itImp=m_ImperList.begin();itImp!=m_ImperList.end();
	itImp++){
		xrandom -= 1/itImp->TotalCost;
		if(xrandom <= 0){
			itRandomImp = itImp;
			break;
		}
	}

	m_ImperList.sort();
	Country_Profile ElimImp = m_ImperList.back().Imper;
	if(m_ImperList.back().ColonyList.empty()){// 如果已经没殖民地了，就把自己作为殖民地给随机帝国
		itRandomImp->ColonyList.push_back(ElimImp);
		m_ImperList.pop_back();
		m_ImpNum = m_ImperList.size();
		return;
	}
	else{
		list<Country_Profile>::iterator it = m_ImperList.back().ColonyList.end();// Get the weakest colony of weekest
		it--;
		itRandomImp->ColonyList.push_back(*it);
		m_ImperList.back().ColonyList.pop_back();
		return;
	}
}

// 对每一个帝国势力，找到其之后与其cost相等的帝国势力，殖民后者与后者的殖民地
void ICA::Merge_Similar_Impers(){
	for(list<Imper_Profile>::iterator it=m_ImperList.begin();it!=m_ImperList.end();it++){
		double key = it->Imper.Cost;
		list<Imper_Profile>::iterator it1=it;
		while(it1!=m_ImperList.end()){// 遍历
			advance(it1,1);
			// 要两个it是因为可能不止一个满足条件，要继续寻找
			// 其实可以把it1移到it2原来的位置，减少重复查找
			// 找到从it1以后帝国势力cost=t1的帝国指针，赋值给it2
			list<Imper_Profile>::iterator it2 = 
			find_if(it1,m_ImperList.end(), 
			[key](const Imper_Profile & m) -> bool { return 
			m.Imper.Cost==key
			// (m.Imper.Cost > key-1 && m.Imper.Cost < key+1)
			; });

			if(it2!=m_ImperList.end()){// 即存在it2
				it->ColonyList.insert( it->ColonyList.end(), it2->ColonyList.begin(), it2->ColonyList.end() );//殖民it2的殖民地
				it->ColonyList.push_back(it2->Imper);//殖民it2
				m_ImperList.erase(it2);
			}
		}
		
	}
}

// 主函数
double ICA::Compet(map<int,double> &Imperialist){
	int n = 0;
	double costmax = DBL_MAX;
	InitializeCountries();
	InitializeImpires();
	m_LogFile<<"\nSecond"<<"\t"<<"Decade"<<"\t"<<"ImpNum"<<"\t"<<"Best Imper Cost";
	while(n<=m_DecadeNum && m_ImperList.size()>=1){
		Assimilate_Clony_to_Imper();
		Doing_Revolution();
		CountryCostCalc();
		Colony_Imper_swap();
		Eliminate_Weakest_Imper();
		Merge_Similar_Impers();
		m_ImperList.sort();
		unsigned long int t = m_Timer.GetElapsedTime();
		m_LogFile<<"\n"<<setw(12)<<right<<t/1000<<"\t\t"<<setw(12)<<right<<n++<<"\t"<<setw(12)<<right<<m_ImperList.size()
		<<"\t\t"<<setw(12)<<right<<m_ImperList.begin()->TotalCost;
		m_PlotFile<<t/1000<<" "<<n<<" "<<m_ImperList.size()<<" "<<m_ImperList.begin()->TotalCost<<endl;
		// 更新cost = 帝国最大势力的cost，log
		if(m_ImperList.begin()->Imper.Cost < costmax){
			costmax = m_ImperList.begin()->Imper.Cost;
			cout<<"\nDecade=\t"<<n<<"\tImperNum=\t"<<m_ImperList.size()<<"\tcostmax=\t"<<m_ImperList.begin()->TotalCost<<"\n";
			cout<<"\nlast Imp:\t"<<m_ImperList.back().ColonyList.size();
			cout<<"\nbest Imp:\t"<<m_ImperList.front().ColonyList.size();
		}
		else{
			cout<<"\nDecade=\t"<<n<<"\tImperNum=\t"<<m_ImperList.size()<<"\tcostmax=\t"<<m_ImperList.begin()->TotalCost<<"\n";
			cout<<"\nlast Imp:\t"<<m_ImperList.back().ColonyList.size();
			cout<<"\nbest Imp:\t"<<m_ImperList.front().ColonyList.size();
		}
		if(n%100==0)
			cout<<"\nnow "<<n<<".";
	}
	cout<<"\n";
	m_ImperList.sort();
	Imper_Profile BestImp = m_ImperList.front();
	Imperialist = BestImp.Imper.Country;
	return BestImp.Imper.Cost;
}
ICA::~ICA(void)
{
	m_DataFile.close();
	m_LogFile.close();
	m_PlotFile.close();
}
